<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        d{
            transform: scale(0.8);
        }
    </style>
</head>
<body>
    <div id="main"></div>
    
    <script>
        const td_size = 40;

        class Vec{
            constructor(x, y){
                this.x = x;
                this.y = y;
            }

            static changeX(dire, old_vec, ele){
                let newX = old_vec.x + 0.25 * dire;

                ele.style.left = newX * td_size + "px";
                return new Vec(newX, old_vec.y);
            }
            
        }

        class Empty{
            constructor(pos){
                this.pos = pos;
            }
        }

        class Wall{
            constructor(pos){
                this.style = {
                    "background-color": "#CDDEC1"
                }
                this.pos = pos;
            }
        }

        class Lava{
            constructor(pos){
                this.style = {
                    "background-color": "#CC564C"
                }
                this.pos = pos;
            }
        }

        class Player{
            constructor(pos){
                this.style = {
                    transform: "scaleX(0.7)",
                    "background-color": "#343730"
                };
                this.pos = pos;
                this.dom_ele = document.createElement("div");
                Player.handleMove(this, this.dom_ele);
            }

            static handleMove(player, ele){
                document.addEventListener("keydown", function(e){
                    console.log(e);
                    switch(e.code){
                        case "ArrowRight":
                            player.pos = Vec.changeX(1, player.pos, ele);
                            break;
                        case "ArrowLeft":
                            player.pos = Vec.changeX(-1, player.pos, ele);
                            break;
                    }
                }, false);
            }
        }

        class Coins{
            constructor(pos){
                this.style = {
                    transform: "scale(0.5)",
                    "background-color": "#BBC558"
                }
                this.pos = pos;
            }
        }

        const levelChars = {
            ".": Empty, "#": Wall, "+": Lava,
            "@": Player, "o": Coins,
            "=": Lava, "|": Lava, "v": Lava
        };

        class Level{
            constructor(map){
                let rows = map.trim().split("\n").map( line => [...line.trim()] );
                this.width = rows.length;
                this.height = rows[0].length;
                this.rows = rows.map( (row, y) => {
                    return row.map( (item, x) => {
                        return new levelChars[item](new Vec(x, y));
                    } )
                } );
            }

            static setGlobalStyle(td_size){
                const main_box = document.getElementById("main");
                let table = document.createElement("table");
                let style = document.createElement("style");

                table.setAttribute("cellpadding", "0");
                table.setAttribute("cellspacing", "0");
                table.setAttribute("id", "game");

                style.innerHTML = `
                    #game{
                        position: relative;
                    }
                    #game td{
                        width: ${td_size}px;
                        height: ${td_size}px;
                        background-color: #2A91C0;
                    }
                    #game td div{
                        width: ${td_size}px;
                        height: ${td_size}px;
                        position: absolute;
                    }
                `;
                document.head.appendChild(style);
                main_box.appendChild(table);
            }

            static drawGame(level, td_size){
                let table = document.getElementById("game");

                level.rows.map( (row, y) => {
                    let tr = document.createElement("tr");

                    row.map( (item, x) => {
                        let td = document.createElement("td");
                        let inner = item.dom_ele ? item.dom_ele : document.createElement("div");

                        item.style = Object.assign({}, item.style, {
                            left: item.pos.x*td_size + "px",
                            top: item.pos.y*td_size + "px"
                        })
                        inner.style = Level.transStyle(item.style);
                        td.appendChild(inner);
                        tr.appendChild(td);
                    } )
                    table.appendChild(tr);
                } )
            }

            static transStyle(style){
                let rel = "";

                if(!style) return;
                Object.keys(style).map(item => {
                    rel += `${item}: ${style[item]};`;
                })
                return rel;
            }
        }

        let simpleLevelPlan = `
            ......................
            ..#................#..
            ..#..............=.#..
            ..#.........o.o....#..
            ..#.@......#####...#..
            ..#####............#..
            ......#++++++++++++#..
            ......##############..
            ......................
        `;
        let l1 = new Level(simpleLevelPlan);
        Level.setGlobalStyle(40);
        Level.drawGame(l1, 40);
    </script>
</body>
</html>